home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
ip
/
ka9q
/
MNetsrc.hqx
/
Mac TCP_IP Source v.33
/
nr4user.c
< prev
next >
Wrap
Text File
|
1989-01-13
|
5KB
|
214 lines
/* net/rom level 4 (transport) protocol user level calls
* Copyright 1989 by Daniel M. Frank, W9NK. Permission granted for
* non-commercial distribution only.
*/
#include <stdio.h>
#include "global.h"
#include "mbuf.h"
#include "timer.h"
#include "ax25.h"
#include "lapb.h"
#include "netrom.h"
#include "nr4.h"
#include <ctype.h>
#undef NR4DEBUG
/* Open a NET/ROM transport connection */
struct nr4cb *
open_nr4(node,user,r_upcall,t_upcall,s_upcall,puser)
struct ax25_addr *node ; /* destination node address */
struct ax25_addr *user ; /* local ax25 user callsign */
void (*r_upcall)() ; /* received data upcall */
void (*t_upcall)() ; /* transmit upcall */
void (*s_upcall)() ; /* state change upcall */
char *puser ; /* pointer to upper level control block */
{
struct nr4cb *cb ;
struct nr4hdr hdr ;
if ((cb = new_n4circ()) == NULLNR4CB)
return NULLNR4CB ; /* No circuits available */
/* Stuff what info we can into control block */
cb->user = *node ; /* When we initiate, user is remote node */
cb->node = *node ;
cb->luser = *user ; /* Save local user for connect retries */
cb->r_upcall = r_upcall ;
cb->t_upcall = t_upcall ;
cb->s_upcall = s_upcall ;
cb->puser = puser ;
/* Format connect request header */
hdr.opcode = NR4OPCONRQ ;
hdr.u.conreq.myindex = cb->mynum ;
hdr.u.conreq.myid = cb->myid ;
hdr.u.conreq.window = Nr4window ;
hdr.u.conreq.user = *user ;
/* The choice of mycall here is suspect. If I have a unique */
/* callsign per interface, then a layer violation will be */
/* required to determine the "real" callsign for my (virtual) */
/* node. This suggests that callsign-per-interface is not */
/* desirable, which answers *that* particular open question. */
hdr.u.conreq.node = mycall ;
/* Set and start connection retry timer */
cb->cdtries = 1 ;
cb->srtt = Nr4irtt ;
cb->tcd.start = (2 * cb->srtt) / MSPTICK ;
cb->tcd.func = nr4cdtimeout ;
cb->tcd.arg = (char *)cb ;
start_timer(&cb->tcd) ;
/* Send connect request packet */
nr4sframe(node, &hdr, NULLBUF) ;
/* Set up initial state and signal state change */
cb->state = NR4STDISC ;
nr4state(cb, NR4STCPEND) ;
/* Return control block address */
return cb ;
}
/* Send a net/rom transport data packet */
int
send_nr4(cb,bp)
struct nr4cb *cb ;
struct mbuf *bp ;
{
if (cb == NULLNR4CB || bp == NULLBUF)
return -1 ;
enqueue(&cb->txq,bp) ;
return nr4output(cb) ;
}
/* Receive incoming net/rom transport data */
struct mbuf *
recv_nr4(cb,cnt)
struct nr4cb *cb ;
int16 cnt ;
{
struct mbuf *bp ;
if (cb->rxq == NULLBUF)
return NULLBUF ;
bp = cb->rxq ; /* Just give `em everything */
cb->rxq = NULLBUF ;
/* Since we took everything, we always go unchoked. If we */
/* ever change this code to use cnt, or make it a real packet */
/* delivery, there will have to be a check to see if the queue */
/* has gotten short enough yet. */
if (cb->qfull) {
cb->qfull = 0 ; /* Choke flag off */
nr4ackit((char *)cb) ; /* Get things rolling again */
}
return bp ;
}
/* Close a NET/ROM connection */
void
disc_nr4(cb)
struct nr4cb *cb ;
{
struct nr4hdr hdr ;
int i ;
if (cb->state != NR4STCON)
return ;
stop_timer(&cb->tchoke) ;
/* Clear out the transmit queue and window */
free_q(&cb->txq) ;
for (i = 0 ; i < cb->window ; i++) {
free_mbuf(cb->txbufs[i].data) ;
cb->txbufs[i].data = NULLBUF ;
stop_timer(cb->txbufs[i].tretry) ;
}
/* Format disconnect request packet */
hdr.opcode = NR4OPDISRQ ;
hdr.yourindex = cb->yournum ;
hdr.yourid = cb->yourid ;
/* Set and start timer */
cb->cdtries = 1 ;
cb->tcd.start = (2 * cb->srtt) / MSPTICK ;
cb->tcd.func = nr4cdtimeout ;
cb->tcd.arg = (char *)cb ;
start_timer(&cb->tcd) ;
/* Send packet */
nr4sframe(&cb->node, &hdr, NULLBUF) ;
/* Signal state change */
nr4state(cb, NR4STDPEND) ;
}
/* Abruptly terminate a NET/ROM transport connection */
void
reset_nr4(cb)
struct nr4cb *cb ;
{
cb->dreason = NR4RRESET ;
nr4state(cb,NR4STDISC) ;
}
/* Force retransmission on a NET/ROM transport connection */
int
kick_nr4(cb)
struct nr4cb *cb ;
{
unsigned seq ;
struct timer *t ;
if(!nr4valcb(cb))
return -1 ;
switch (cb->state) {
case NR4STCPEND:
case NR4STDPEND:
stop_timer(&cb->tcd) ;
nr4cdtimeout((char *)cb) ;
break ;
case NR4STCON:
if (cb->nextosend != cb->ackxpected) { /* if send window is open: */
for (seq = cb->ackxpected ;
nr4between(cb->ackxpected, seq, cb->nextosend) ;
seq = (seq + 1) & NR4SEQMASK) {
t = &cb->txbufs[seq % cb->window].tretry ;
stop_timer(t) ;
t->state = TIMER_EXPIRE ; /* fool retry routine */
}
nr4txtimeout((char *)cb) ;
}
break ;
}
return 0 ;
}